package com.wocai.jrt.utils;

import java.io.IOException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.timevale.esign.sdk.tech.bean.AccountBean;
import com.timevale.esign.sdk.tech.bean.OrganizeBean;
import com.timevale.esign.sdk.tech.bean.PersonBean;
import com.timevale.esign.sdk.tech.bean.PosBean;
import com.timevale.esign.sdk.tech.bean.result.AddAccountResult;
import com.timevale.esign.sdk.tech.bean.result.AddSealResult;
import com.timevale.esign.sdk.tech.bean.result.LoginResult;
import com.timevale.esign.sdk.tech.bean.result.Result;
import com.timevale.esign.sdk.tech.bean.seal.OrganizeTemplateType;
import com.timevale.esign.sdk.tech.bean.seal.PersonTemplateType;
import com.timevale.esign.sdk.tech.bean.seal.SealColor;
import com.timevale.esign.sdk.tech.impl.constants.OrganRegType;
import com.timevale.esign.sdk.tech.impl.constants.SignType;
import com.timevale.esign.sdk.tech.service.AccountService;
import com.timevale.esign.sdk.tech.service.EsignsdkService;
import com.timevale.esign.sdk.tech.service.SealService;
import com.timevale.esign.sdk.tech.service.SignService;
import com.timevale.esign.sdk.tech.service.factory.AccountServiceFactory;
import com.timevale.esign.sdk.tech.service.factory.EsignsdkServiceFactory;
import com.timevale.esign.sdk.tech.service.factory.SealServiceFactory;
import com.timevale.esign.sdk.tech.service.factory.SignServiceFactory;
import com.timevale.tgtext.text.pdf.PdfReader;
import com.vteba.utils.common.PropsUtils;
import com.wocai.jrt.employee.model.Org;
import com.wocai.jrt.investor.model.Investor;

/***
 * 
 * @author linbaolu
 * @date 2016年3月23日 上午11:06:20
 */
public class ESignUtils {
	private static final Logger LOGGER = LoggerFactory
			.getLogger(ESignUtils.class);
	private static EsignsdkService SDK = EsignsdkServiceFactory.instance();
	private static AccountService ACCOUNT_SERVICE = AccountServiceFactory
			.instance();
	private static SealService SEAL = SealServiceFactory.instance();
	private static SignService SIGN_SERVICE = SignServiceFactory.instance();

	private ESignUtils() {
	}

	/***
	 * idNo只支持身份证/护照
	 * 
	 * @param investor
	 * @param org
	 *            regType : 0-组织机构代码号，1-社会信用代码号',
	 * @param pdfPath
	 * @return
	 */
	public static String sign(Investor investor, Org org, String pdfPath) {
		String resultFinal = null;

		try {

			// 登陆成功返回devId
			String devId = login();

			if (null == devId) {
				LOGGER.info("登录失败！");
				return resultFinal;
			}
			
			/*
			 * 移除手机号、邮箱、地址
			 */
			// 创建个人bean
			PersonBean personBean = new PersonBean();
			personBean.setName(investor.getName())
					.setIdNo(investor.getIdcard())
					.setOrgan(investor.getCompany());

			// 创建企业bean
			OrganizeBean organizeBean = new OrganizeBean();
			organizeBean.setName(org.getName()).setUserType(2)
					.setLegalName(org.getContact())
					.setLegalIdNo(org.getContactIdcard());

			if (org.getRegType() == 0) {
				organizeBean.setOrganCode(org.getOrganCode());
			} else if (org.getRegType() == 1) {
				organizeBean.setRegType(OrganRegType.MERGE).setOrganCode(
						org.getOrganCode());
			}

			// 创建个人账户
			String personUserId = addAcount("person", devId, personBean);
			if (null == personUserId) {
				LOGGER.info("创建个人账户失败！");
				return resultFinal;
			}

			// 创建企业账户
			String organizeUserId = addAcount("organize", devId, organizeBean);
			if (null == organizeUserId) {
				LOGGER.info("创建企业账户失败！");
				return resultFinal;
			}

			// 创建个人印章
			String personSeal = createSeal("person", devId, personUserId, 3);// 3-横向宋体，4-方形宋体
			if (personSeal == null) {
				LOGGER.info(personUserId + "创建个人印章失败！");
				return resultFinal;
			} else
				LOGGER.info(personUserId + " 创建个人印章成功");

			// 创建企业印章  2-企业圆形印章，1-椭圆印章
			String organizeSeal = createSeal("organize", devId, organizeUserId,
					2);

			if (organizeSeal == null) {
				LOGGER.info(organizeUserId + "创建企业印章失败！");
				return resultFinal;
			} else
				LOGGER.info(organizeUserId + "创建企业印章成功");

			String newFilePath = MyFileUtils.getFilePath(
					pdfPath.substring(pdfPath.lastIndexOf("/") + 1,
							pdfPath.length()), MyFileUtils.PDF_TYPE);

			// pdf 页数
			PdfReader reader = new PdfReader(pdfPath);
			int pdfNum = reader.getNumberOfPages();
			reader.close();

			// 添加个人印章
			PosBean personPosBean = new PosBean();
			personPosBean.setPosX(200);
			personPosBean.setPosY(100);
			personPosBean.setPosPage(Integer.toString(pdfNum));

			String result = sign(devId, personUserId, personSeal, pdfPath,
					newFilePath, personPosBean);
			if (result == null) {
				LOGGER.info(personUserId + "添加个人印章失败！");
				return resultFinal;
			} else
				LOGGER.info(personUserId + "添加个人印章成功！文件路径:" + result);
			result = null;

			// 添加企业印章
			PosBean organizePosBean = new PosBean();
			organizePosBean.setPosX(400);
			organizePosBean.setPosY(100);
			organizePosBean.setPosPage(Integer.toString(pdfNum));

			result = sign(devId, organizeUserId, organizeSeal, newFilePath,
					newFilePath, organizePosBean);
			if (result == null) {
				LOGGER.info(organizeUserId + "添加企业印章失败！");
				return resultFinal;
			} else {
				LOGGER.info(organizeUserId + "添加企业印章成功！文件路径:" + result);
				resultFinal = result;
			}

		} catch (IOException e) {
			LOGGER.error("MyFileUtils.getFilePath 获取文件路径失败！, errorMsg=[{}]",
					e.getMessage());
		}

		return resultFinal;
	}

	/***
	 * 初始化E签宝SDK，并登陆；登陆24小时内有效，返回devId
	 */
	public static String login() {

		// 初始化E签宝SDK
		Result result = SDK.init(PropsUtils.get("projectId"),
				PropsUtils.get("projectSecret"));
		if (0 != result.getErrCode()) {
			LOGGER.error("初始化失败，错误码=" + result.getErrCode() + ",错误信息="
					+ result.getMsg());
			return null;
		}

		LOGGER.info("初始化成功，开始执行项目登录...");

		// 使用初始化设置的项目编号和项目验证码做项目账户登录
		LoginResult loginResult = SDK.login();
		if (0 != loginResult.getErrCode()) {
			LOGGER.error("验证处理失败！");
		}

		// 设置项目账户标识，后续接口调用时可以从session中获取
		String devId = loginResult.getAccountId();
		LOGGER.info("验证处理成功! devId:" + devId);

		return devId;
	}

	/***
	 * 在E签宝上注册个人或企业信息，返回userId
	 * 
	 * @param accountType
	 * @param devId
	 * @param acount
	 */
	public static String addAcount(String accountType, String devId,
			AccountBean acount) {
		if (accountType.equalsIgnoreCase("person")) {
			return addPerson(devId, (PersonBean) acount);
		} else {
			return addOrganize(devId, (OrganizeBean) acount);
		}
	}

	/***
	 * 创建个人或企业公章
	 * 
	 * @param accountType
	 *            ：person
	 * @param devId
	 * @param userId
	 * @param type
	 *            ：3-横向宋体，4-方形宋体
	 * @return
	 */
	public static String createSeal(String accountType, String devId,
			String userId, int type) {

		if (accountType.equalsIgnoreCase("person")) {
			return createSealPersonal(devId, userId, type);
		} else {
			return createSealOrganize(devId, userId, type);
		}
	}

	/**
	 * 数字签约
	 * 
	 * @param devId
	 * @param userId
	 * @param seal
	 * @param srcPdfFile
	 * @param dstPdfFile
	 * @return
	 */
	public static String sign(String devId, String userId, String seal,
			String srcPdfFile, String dstPdfFile, PosBean pos) {

		// 使用用户印章签名
		Result r = SIGN_SERVICE.localSignPDF(devId, userId, seal, srcPdfFile,
				dstPdfFile, pos, SignType.Single, null);

		if (0 != r.getErrCode()) {

			// 签署失败
			return null;
		}

		// 文件签署成功
		return dstPdfFile;
	}

	private static String addPerson(String devId, PersonBean psn) {

		// 添加个人账户
		AddAccountResult r = ACCOUNT_SERVICE.addAccount(devId, psn);
		if (0 != r.getErrCode() || null == r.getAccountId()
				|| r.getAccountId().isEmpty()) {
			LOGGER.error("添加个人账户失败！");
			return null;
		}

		String userId = r.getAccountId();
		LOGGER.info("添加个人账户成功, userId=[{}]", userId);

		return userId;
	}

	private static String addOrganize(String devId, OrganizeBean org) {

		// 添加企业账户
		AddAccountResult r = ACCOUNT_SERVICE.addAccount(devId, org);
		if (0 != r.getErrCode() || null == r.getAccountId()
				|| r.getAccountId().isEmpty()) {
			LOGGER.error("添加企业账户失败！");
			return null;
		}

		String userId = r.getAccountId();
		LOGGER.info("添加企业账户成功, userId=[{}]", userId);

		return userId;
	}

	private static String createSealPersonal(String devId, String userId,
			int type) {

		PersonTemplateType seal;

		switch (type) {

		case 1:
			seal = PersonTemplateType.FZKC;
			break;

		case 2:
			seal = PersonTemplateType.HYLSF;
			break;

		case 3:
			seal = PersonTemplateType.RECTANGLE;
			break;

		case 4:
			seal = PersonTemplateType.SQUARE;
			break;

		case 5:
		default:
			seal = PersonTemplateType.YYGXSF;
			break;
		}

		AddSealResult r = SEAL.addTemplateSeal(devId, userId, seal,
				SealColor.RED);
		if (0 != r.getErrCode()) {
			return null;
		}

		return r.getSealData();
	}

	private static String createSealOrganize(String devId, String userId,
			int type) {

		OrganizeTemplateType seal;

		switch (type) {

		case 1:
			seal = OrganizeTemplateType.OVAL;
			break;

		case 2:
		default:
			seal = OrganizeTemplateType.STAR;
			break;
		}

		AddSealResult r = SEAL.addTemplateSeal(devId, userId, seal,
				SealColor.RED, "★★★★★", "合同专用章");
		if (0 != r.getErrCode()) {
			return null;
		}

		return r.getSealData();
	}

}
